package org.boticelli.controller;

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.boticelli.model.LogEntry;
import org.boticelli.model.LogType;
import org.boticelli.util.ColorHelper;
import org.boticelli.util.Util;

/**
 * Decorates a {@link LogEntry} with color information and a nick getter to
 * present the log in the view layer
 * @author shelmberger
 *
 */
public class DecoratedLog
        implements Serializable
{
    private static final String BOLD_TAG_CLOSE = "</b>";

    private static final String BOLD_TAG_OPEN = "<b>";

    private static final char BOLD = '\002';

    private static final long serialVersionUID = -2453633261043429327L;

    private LogEntry log;

    private transient String nick;

    private float score;

    private DecoratedLog(LogEntry log)
    {
        this.log = log;
    }

    public float getScore()
    {
        return score;
    }

    public void setScore(float score)
    {
        this.score = score;
    }

    public String getNick()
    {
        if (nick == null)
        {
            String ident = log.getIdent();
            int pos = ident.indexOf('!');
            if (pos >= 0)
            {
                nick = ident.substring(0, pos);
            }
            else
            {
                nick = ident;
            }
        }
        return nick;
    }

    private int colorIndex;

    public String getColorClass()
    {
        return "color"+colorIndex;
    }

    public void setColorIndex(int color)
    {
        this.colorIndex = color;
    }

    public Timestamp getMoment()
    {
        return log.getMoment();
    }

    public String getIdent()
    {
        return log.getIdent();
    }

    private String text;

    public String getText()
    {
        if (this.text == null)
        {
            this.text = linkifyURLs( convertBoldCharToBoldTag(Util.unicodeHtmlEscape(log.getText(), true)));
        }

        return this.text;
    }

    public Integer getDay()
    {
        return log.getDay();
    }

    private final static Pattern URL_PATTERN=Pattern.compile("((http|https|ftp)://[^\\s]+(\\s|))", Pattern.CASE_INSENSITIVE);

    private static String linkifyURLs(String s)
    {
        StringBuffer sb=new StringBuffer();
        Matcher m=URL_PATTERN.matcher(s);

        while (m.find())
        {
            m.appendReplacement(sb, "<a href=\"$1\">$1</a>");
        }
        m.appendTail(sb);

        return sb.toString();
    }

    private static String convertBoldCharToBoldTag(String text)
    {
        boolean inBold=false;
        int pos;
        int lastPos=0;
        StringBuilder sb=new StringBuilder();
        while ((pos=text.indexOf(BOLD,lastPos)) >= 0)
        {
            if ( pos - lastPos > 0)
            {
                sb.append(text.substring(lastPos,pos));
            }
            lastPos=pos+1;

            if (inBold)
            {
                sb.append(BOLD_TAG_CLOSE);
                inBold=false;
            }
            else
            {
                sb.append(BOLD_TAG_OPEN);
                inBold=true;
            }
        }

        sb.append(text.substring(lastPos));

        if (inBold)
        {
            sb.append(BOLD_TAG_CLOSE);
        }
        return sb.toString();
    }

    public LogType getType()
    {
        return log.getType();
    }

    /**
     * Returns a list of decorated logs for the given list of logs.
     * @param logsIn
     * @return
     */
    public static List<DecoratedLog> decorate(List<LogEntry> logsIn)
    {
        ColorHelper colorHelper = new ColorHelper();
        List<DecoratedLog> logs = new ArrayList<DecoratedLog>();
        for (LogEntry raw : logsIn)
        {
            DecoratedLog log = new DecoratedLog(raw);
            log.setColorIndex(colorHelper.getColorIndexFor(log.getIdent()));
            logs.add(log);
        }
        return logs;
    }

    public static void main(String[] args)
    {
        System.out.println(linkifyURLs("http://google.de"));
    }
}
